package com.go.where.family.api.servlet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.go.where.family.api.constants.Constant;
import com.go.where.family.api.scoket.Head;
import com.go.where.family.api.scoket.SocketDTO;
import com.go.where.family.api.scoket.TransmissionCode;
import com.go.where.family.api.server.HttpServerStartMain;
import com.go.where.family.api.utils.CommonUtil;
import com.go.where.family.api.utils.IpUtil;
import com.go.where.family.api.utils.MD5Util;
import com.go.where.family.api.utils.ParseWeichatXml;
import com.go.where.family.api.utils.ServletUtil;
import com.go.where.family.api.vo.OrderVo;
import com.go.where.family.api.vo.WeichatVo;
import com.google.gson.Gson;

/**
 * 微信支付状态回调
 * 
 * @description
 * @author
 * @date
 */
public class WeichatCallbackServlet extends SuperServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private static Logger log = Logger.getLogger(WeichatCallbackServlet.class);
	private static Gson gson = CommonUtil.gson();

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		req.setAttribute("org.eclipse.jetty.server.Request.queryEncoding",
				"UTF-8");
		resp.setContentType("text/html;charset=UTF-8");
		resp.setStatus(HttpServletResponse.SC_OK);

		BufferedReader reader = new BufferedReader(new InputStreamReader(req
				.getInputStream()));
		String line = null;
		StringBuffer sb = new StringBuffer();
		while ((line = reader.readLine()) != null) {
			sb.append(line);
		}
		String xmlParameter = sb.toString();

		log.info("微信异步通知：xmlParameter：" + xmlParameter);
		try {
			if (xmlParameter != null) {
				WeichatVo weichat = ParseWeichatXml.parse(xmlParameter);
				if (weichat != null) {
					if ("SUCCESS".equals(weichat.getReturnCode())) {
						String sourceSignStr = this
								.createWeichatSignSource(weichat);
						String sgn = MD5Util.MD5Encode(
								sourceSignStr
										+ "&key="
										+ HttpServerStartMain
												.getValue("wei.chat.md5.key"))
								.toUpperCase();
						if (sgn.endsWith(weichat.getSign())) {// 数据校验成功
							OrderVo vo = new OrderVo();
							vo.setOrderId(weichat.getOutTradeNo());
							vo.setTpPayNo(weichat.getTransactionId());
							vo.setTradeStatus(weichat.getResultCode());
							vo.setPayType("2");
							SocketDTO dto = sendMessage(vo, req);
							Head head = dto.getHead();
							String resCode = head.getResponseCode();
							// String resMsg = head.getResponseMessage();
							String body = dto.getBody();
							if (TransmissionCode.SUCCESS.getCode().equals(
									resCode)) {
								// 把service中返回的信息转成对应的json格式字符串，返回给接口调用者
								if (StringUtils.isNotBlank(body)) {
									boolean res = gson.fromJson(body,
											Boolean.class);
									if (res) {
										ServletUtil.writeResXML(resp,
												"SUCCESS", "回调成功");
									} else {
										ServletUtil.writeResXML(resp, "FAIL",
												"回调失败");
									}
								} else {
									ServletUtil.writeResXML(resp, "FAIL",
											"回调失败");
								}
							} else {
								log
										.error("内部通信异常，"
												+ head.getResponseMessage());
								ServletUtil.writeResXML(resp, "FAIL", "回调失败");
							}

						} else {
							log.error("微信异步通知，验签失败");
							ServletUtil.writeResXML(resp, "FAIL", "校验失败");
						}
					} else {
						log.error("微信异步通知，通信失败");
						ServletUtil.writeResXML(resp, "FAIL", "通信失败");
					}
				} else {
					log.error("微信异步通知，通信失败");
					ServletUtil.writeResXML(resp, "FAIL", "通信失败");
				}
			} else {
				log.error("微信异步通知，通知参数为空");
				ServletUtil.writeResXML(resp, "FAIL", "通知参数为空");
			}

		} catch (Exception e) {
			log.error("异常信息", e);
			ServletUtil.writeResXML(resp, "FAIL", "未知原因错误");
		}
	}

	private String createWeichatSignSource(WeichatVo weichat) {
		TreeMap<String, Object> treeMap = new TreeMap<String, Object>(
				new Comparator<String>() {
					public int compare(String o1, String o2) {
						return o1.compareTo(o2);
					}
				});
		if (StringUtils.isNotBlank(weichat.getReturnCode())) {
			treeMap.put("return_code", weichat.getReturnCode());
		}
		if (StringUtils.isNotBlank(weichat.getReturnMsg())) {
			treeMap.put("return_msg", weichat.getReturnMsg());
		}
		if (StringUtils.isNotBlank(weichat.getAppid())) {
			treeMap.put("appid", weichat.getAppid());
		}
		if (StringUtils.isNotBlank(weichat.getMchid())) {
			treeMap.put("mch_id", weichat.getMchid());
		}
		if (StringUtils.isNotBlank(weichat.getNonceStr())) {
			treeMap.put("nonce_str", weichat.getNonceStr());
		}
		if (StringUtils.isNotBlank(weichat.getResultCode())) {
			treeMap.put("result_code", weichat.getResultCode());
		}
		if (StringUtils.isNotBlank(weichat.getErrCode())) {
			treeMap.put("err_code", weichat.getErrCode());
		}
		if (StringUtils.isNotBlank(weichat.getErrCodeDes())) {
			treeMap.put("err_code_des", weichat.getErrCodeDes());
		}
		if (StringUtils.isNotBlank(weichat.getOpenId())) {
			treeMap.put("openid", weichat.getOpenId());
		}
		if (StringUtils.isNotBlank(weichat.getIsSubscribe())) {
			treeMap.put("is_subscribe", weichat.getIsSubscribe());
		}
		if (StringUtils.isNotBlank(weichat.getTradeType())) {
			treeMap.put("trade_type", weichat.getTradeType());
		}
		if (StringUtils.isNotBlank(weichat.getBankType())) {
			treeMap.put("bank_type", weichat.getBankType());
		}
		if (StringUtils.isNotBlank(weichat.getTotalFee())) {
			treeMap.put("total_fee", weichat.getTotalFee());
		}
		if (StringUtils.isNotBlank(weichat.getFeeType())) {
			treeMap.put("fee_type", weichat.getFeeType());
		}
		if (StringUtils.isNotBlank(weichat.getCashFee())) {
			treeMap.put("cash_fee", weichat.getCashFee());
		}
		if (StringUtils.isNotBlank(weichat.getCashFeeType())) {
			treeMap.put("cash_fee_type", weichat.getCashFeeType());
		}
		if (StringUtils.isNotBlank(weichat.getTransactionId())) {
			treeMap.put("transaction_id", weichat.getTransactionId());
		}
		if (StringUtils.isNotBlank(weichat.getOutTradeNo())) {
			treeMap.put("out_trade_no", weichat.getOutTradeNo());
		}
		if (StringUtils.isNotBlank(weichat.getTimeEnd())) {
			treeMap.put("time_end", weichat.getTimeEnd());
		}

		StringBuilder sbu = new StringBuilder();
		Set<Map.Entry<String, Object>> set = treeMap.entrySet();
		Iterator<Map.Entry<String, Object>> it = set.iterator();
		Map.Entry<String, Object> entry = null;
		while (it.hasNext()) {
			entry = it.next();
			if (entry.getValue() != null) {
				if (StringUtils.isNotBlank(entry.getValue().toString())) {
					sbu.append(entry.getKey().toString());
					sbu.append("=");
					sbu.append(entry.getValue().toString());
					sbu.append("&");
				}
			}
		}
		String data = sbu.toString();
		data = data.substring(0, data.length() - 1);
		return data;
	}

	/**
	 * 向service服务发送请求
	 * 
	 * @param t
	 * @param req
	 * @return
	 */
	private SocketDTO sendMessage(OrderVo vo, HttpServletRequest req) {
		Head head = new Head();
		head.setRequestId(UUID.randomUUID().toString());
		head.setServiceCode(Constant.ORDER_CALLBACK);
		head.setIp(IpUtil.getIpAddr(req));
		head.setUserId("api");
		return super.send(head, vo);
	}

}
